//
//  NetworkManager.swift
//

import Alamofire
import CleanJSON

class NetworkManager: NSObject {

    static let share = NetworkManager()
    private var dataRequest = [String: DataRequest]()
    
    public func request(_ target: TargetType) -> NetworkManager {
        
        let url = target.baseURL + target.path
        let key = requestKey(url, target.parameters)
        let request = AF.request(url,
                                 method: target.method,
                                 parameters: target.parameters,
                                 encoding: target.encoding,
                                 headers: target.headers)
        
        dataRequest[key] = request
        
        return self
    }
    
    public func responseData<T: Codable>(_ type: T.Type,
                                         completion: @escaping (Response<T>) -> Void,
                                         failure: @escaping (AppError) -> Void) {
        dataRequest.forEach { key, request in
            dataRequest.removeValue(forKey: key)
            request.responseData { response in
                switch response.result {
                case let .success(data):
                    if let responseData = try? CleanJSONDecoder().decode(Response<T>.self, from: data) {
                        if !responseData.success {
                            failure(responseData.appError)
                            return
                        }
                        completion(responseData)
                    } else {
                        failure(AppError(code: 0000, errorMessage: "数据解析失败"))
                    }
                case let .failure(error):
                    failure(error.appError)
                }
            }
        }
    }
    
    public func responseAudioData<T: Codable>(_ type: T.Type,
                                              completion: @escaping (AudioResponse<T>) -> Void,
                                              failure: @escaping (AppError) -> Void) {
        
        dataRequest.forEach { key, request in
            dataRequest.removeValue(forKey: key)
            request.responseData { response in
                switch response.result {
                case let .success(data):
                    if let responseData = try? CleanJSONDecoder().decode(AudioResponse<T>.self, from: data) {
                        
                        if !responseData.success {
                            failure(responseData.appError)
                            return
                        }
                        completion(responseData)
                    } else {
                        failure(AppError(code: 0000, errorMessage: "数据解析失败"))
                    }
                case let .failure(error):
                    if error.appError.code != -999 {
                        failure(error.appError)
                    }
                }
            }
        }
    }
}

extension NetworkManager {
    
    public func download(_ url: String,
                         to destination: DownloadRequest.Destination? = nil,
                         progress: @escaping (Progress) -> Void,
                         responseURL: @escaping (URL) -> Void,
                         failure: @escaping (AppError) -> Void) {
        AF.download(url, to: destination)
            .downloadProgress(closure: progress)
            .response { response in
            if response.error == nil, let filePath = response.fileURL {
                responseURL(filePath)
            } else {
                failure(AppError(code: -1, errorMessage: "下载失败"))
            }
        }
    }
}

extension NetworkManager {
    
    /// 将url和参数拼接，转换成字符串后md5
    private func requestKey(_ url: String, _ params: [String: Any]?) -> String {
        if let parameters = params {
            let str = url + parameters.dictToSortedString
            return str.MD5String
        }
        return url.MD5String
    }
    
}
